package com.hsmpay.mobile.action.account.officialAccPay;

import com.hsmpay.common.pojo.BasePojo;
import com.hsmpay.common.pojo.qian4.Qian4SendLog;
import com.hsmpay.common.pojo.user.User;
import com.hsmpay.common.util.NumberUtil;
import com.hsmpay.common.util.OrderTypeUtil;
import com.hsmpay.mobile.action.account.scanCodePay.MD5;
import com.hsmpay.mobile.action.account.scanCodePay.ScanCodePayParam;
import com.hsmpay.mobile.action.account.scanCodePay.SignUtils;
import com.hsmpay.mobile.pojo.bank.Bank;
import com.hsmpay.mobile.pojo.other.Settings;
import com.hsmpay.mobile.pojo.terminal.Tchannel;
import com.hsmpay.mobile.pojo.trans.RemoteNotify;
import com.hsmpay.mobile.pojo.trans.TransOrder;
import com.hsmpay.mobile.pojo.trans.TransPriorSettle;
import com.hsmpay.mobile.pojo.user.UserMoney;
import com.hsmpay.mobile.service.account.AccountManageQ4Service;
import com.hsmpay.mobile.service.account.CashMoneyService;
import com.hsmpay.mobile.service.bank.BankService;
import com.hsmpay.mobile.service.other.SettingsService;
import com.hsmpay.mobile.service.trans.*;
import com.hsmpay.mobile.service.user.UserMoneyService;
import com.hsmpay.qian4.pojo.PurchaseResult;
import com.hsmpay.qian4.service.ds.*;
import com.hsmpay.qian4.service.ds.impl.XYScanCodePayServiceImpl;
import com.hsmpay.utils.DesUtil;
import com.hsmpay.utils.SSLClient;
import com.hsmpay.utils.system.ConConfig;
import net.sf.json.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;

import javax.annotation.Resource;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 公众号支付业务
 */
@Controller("officialAccPayAction")
@Scope("prototype")
public class OfficialAccPayAction extends OfficialAccPayBaseAction {

    private static final long serialVersionUID = 7459445231353195197L;
    private Logger log = LoggerFactory.getLogger(OfficialAccPayAction.class);

    @Resource(name = "transRefuseCardService")
    protected TransRefuseCardService<BasePojo, Long> transRefuseCardService;//拒绝卡号交易
    @Resource(name = "transOrderService")
    protected TransOrderService<TransOrder, Long> transOrderService;
    @Resource(name = "accountManageQ4Service")
    protected AccountManageQ4Service<BasePojo, Long> accountManageQ4Service;
    @Resource(name = "qian4SendLogService")
    protected Qian4SendLogService<Qian4SendLog, Long> qian4SendLogService;//发送日志
    @Resource(name = "bankService")
    protected BankService<Bank,Long> bankService;
    @Resource(name="ds_XYScanCodePayService")
    public XYScanCodePayService ds_XYScanCodePayService;
    @Resource(name="ds_JQScanCodePayService")
    public JQScanCodePayService ds_JQScanCodePayService;
    @Resource(name="weixinPayService")
    public WeixinPayService weixinPayService;
    @Resource(name="shangLianChuService")
    public ShangLianChuPayService shangLianChuPayService;
    @Resource(name = "transPriorSettleService")
    private TransPriorSettleService<TransPriorSettle, Long> transPriorSettleService;
    @Resource(name="ds_JQSecondPayService")
    private JQSecondPayService ds_JQSecondPayService;
    @Resource(name = "settingsService")
    protected SettingsService<Settings, Long> settingsService;
    @Resource(name = "cashMoneyService")
    private CashMoneyService<TransOrder, Long> cashMoneyService;
    @Resource(name = "userMoneyService")
    private UserMoneyService<UserMoney, Long> userMoneyService;
    @Resource(name = "remoteNotifyService")
    private RemoteNotifyService remoteNotifyService;
    @Resource(name = "ds_hsmPayService")
    private HsmPayService hsmPayService;
    @Resource(name = "ds_JQQRCodePayService")
    private JQQRCodePayService ds_JQQRCodePayService;

    /**
     * 微信公众号支付
     * @return
     * @throws Exception
     */
    public String OfficialAccPay() throws Exception {
        log.debug("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
        log.debug("XXXXXXXXXXXXXXXXXXXXXXXXX  公众号支付  收款  开始  XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
        log.debug("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");

        String userId = getRequest().getParameter("userId");
        String openId = getRequest().getParameter("openId");
        totalFee = getRequest().getParameter("amt");//此处金额为元

        int appClient = 0;
        String header = getRequest().getHeader("user-agent").toLowerCase();
        if(header.contains("alipay") || header.contains("aliapp")){
            appClient = 1; //AliPay
        }else if(header.contains("micromessenger") || header.contains("mqqbrowser")){
            appClient = 2; //WeChart
        }

        if(StringUtils.isBlank(userId)){
            log.info("支付时, 参数userId为空!");
            sendWeChatErrorMsg("6001","userId");
            return null;
        }

//        if(StringUtils.isBlank(openId)){
//            log.debug("支付时, 参数openId为空!");
//            sendWeChatErrorMsg("6001","openId");
//            return null;
//        }

        //查询用户
//        User user = userService.getUserById(Long.valueOf(userId));
        User user = new User();
        user.setId(Long.valueOf(userId));
        user = userService.searchEntity(user);
        if(null == user){
            log.info("支付时, 用户不存在!");
            sendWeChatErrorMsg("6001","user");
            return null;
        }

        //实名认证未通过不能进行交易
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("code","7102");
        if(1 == user.getDPIStatus().intValue()){
            //支付接口
            payOrder(user,appClient);
        }else if(2 == user.getDPIStatus().intValue()){
            jsonObject.put("msg","商户实名认证审核中，请您耐心等待！");
            sendWeChatMsg(jsonObject.toString());
            return null;
        }else {
            jsonObject.put("msg","商户实名认证失败，请等待商户重新提交实名认证！");
            sendWeChatMsg(jsonObject.toString());
            return null;
        }

//        try {
//            double money = Double.parseDouble(totalFee) / 100;
//            Map<String, Object> map = userTransLimitService.transCheck(Long.valueOf(userId), roleId, null, money, 9L, SCANCODEPAY_FUNCKEY, null);
//            if (map != null) {
//                sendWeChatErrorMsg(map.get("code").toString(), map.get("value").toString());
//                return null;
//            }
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
        return null;
    }

    /**
     * 支付
     * @return
     * @throws Exception
     */
    public String payOrder(User user,Integer appClient) throws Exception {
        functionKey = SCANCODEPAY_FUNCKEY;
        Qian4SendLog send = null;//发送数据
        TransPriorSettle transPriorSettle = null;
        TransOrder transOrder = null;
        ScanCodePayParam scanCodePayParam = null;
        JSONObject result = null;
        try {
            if (!checkPIV(functionKey)) {
                log.info("银行接口暂停使用！");
                return null;
            }
            if (null != user) {
                Object[] resultA = assembleBean(user);
                if (null == resultA) return null;

                send = (Qian4SendLog) resultA[0];
                transOrder = (TransOrder) resultA[1];
                scanCodePayParam = (ScanCodePayParam) resultA[2];

                int channelId = user.getChannelId().intValue();

                if(user.getChannelId() == OfficialAccPayBaseAction.TC_JQ_SECOND){//进钱秒到

                    //获取进钱微信和支付宝秒到接口的状态
                    Settings settings = settingsService.getSettingsByFk("JQ_SECOND_STATUS");
                    Integer weChartStatus = Integer.valueOf(settings.getMainValue());
                    Integer aliPayStatus = Integer.valueOf(settings.getValue2());
                    int defaultChannelId = Integer.valueOf(settings.getValue3());

                    if(StringUtils.isNotBlank(user.getJQCusId()) && StringUtils.isNotBlank(user.getJQMD5Key()) && user.getClearStatus() != 2 && user.getBankStatus() == 1){

                        if(1 == appClient){//AliPay
                            if(1 != aliPayStatus){
                                JSONObject jsonObject = new JSONObject();
                                jsonObject.put("code","7012");
                                jsonObject.put("msg","服务端升级,支付宝接口暂停使用,请您选择微信或其他支付方式!");
                                sendWeChatMsg(jsonObject.toString());
                                return null;
                            }
                            transOrder.setClientType(7);
                        }else if (2 == appClient){//WeChart
                            if(1 != weChartStatus){
                                channelId = defaultChannelId;
                            }else {
                                transOrder.setClientType(8);
                            }
                        }
                    }else{
                        if(1 == appClient){//AliPay
                            JSONObject jsonObject = new JSONObject();
                            jsonObject.put("code","7012");
                            jsonObject.put("msg","报备未完成,暂时不支持支付宝秒到,请先使用微信!(报备需要2~3工作日)");
                            sendWeChatMsg(jsonObject.toString());
                            return null;
                        }else{//WeChart or other
                            channelId = defaultChannelId;
                        }
                    }
                }

                Tchannel tc = tchannelService.searchMobileTchannelByCode(channelId);

                send.setCollectionType(tc.getCode());
                send.setRoleId(user.getRoleId());
                double fee = calculateFee(transOrder.getTransMoney(), transOrder.getFeeRate());
                transOrder.setFeeMoney(fee);
                transOrder.setChargeAmount(transOrder.getTransMoney() - fee);
                transOrder.setOrderTypeId(RECEIVABLES);

                //下订单
                transPriorSettle = accountManageQ4Service.advanceOrder(transOrder, send, send.getCollectionType());
                PurchaseResult rs = null;
                switch (send.getCollectionType()){
                    case OfficialAccPayBaseAction.TC_XY:
                        send.setMerchantId(XYScanCodePayServiceImpl.mchId);
                        rs = ds_XYScanCodePayService.purchase(send,scanCodePayParam,signaturePath);
                        break;
                    case OfficialAccPayBaseAction.TC_JQ:
                        rs = ds_JQScanCodePayService.getQRCode(send,scanCodePayParam,signaturePath);
                        break;
                    case OfficialAccPayBaseAction.TC_WEIXIN:
                    	rs = weixinPayService.getQRCode(send,scanCodePayParam,signaturePath);
                    	break;
                    case OfficialAccPayBaseAction.TC_SHANGLIANCHU:
                    	rs = shangLianChuPayService.getQRCode(send,scanCodePayParam,signaturePath);
                    	break;
                    case OfficialAccPayBaseAction.TC_JQ_SECOND:
                        rs = ds_JQSecondPayService.getQRCode(scanCodePayParam,user,appClient);
                        break;
                    case OfficialAccPayBaseAction.TC_HSM:
                        scanCodePayParam.setVersion("1.0.0");
                        scanCodePayParam.setService("0010");
                        scanCodePayParam.setAppClient(String.valueOf(appClient));
                        rs = hsmPayService.getQRCode(scanCodePayParam);
                        break;
                    case OfficialAccPayBaseAction.TC_JQ_QR:
                        if(user.getRoleType() != 3 && (StringUtils.isBlank(user.getJQCusId()) || StringUtils.isBlank(user.getJQMD5Key()))){
                            log.info("用户未报备,被禁止交易!");
                            JSONObject jsonObject = new JSONObject();
                            jsonObject.put("code","6089");
                            jsonObject.put("msg","亲,您的报备信息正在审核中,请耐心等待...");
                            sendWeChatMsg(jsonObject.toString());
                            return null;
                        }else {
                            rs = ds_JQQRCodePayService.getQRCode(scanCodePayParam,user);
                        }
                        break;
                }

                //需要等待回调通知交易结果
                if(send.getCollectionType() == OfficialAccPayBaseAction.TC_JQ 
                		|| send.getCollectionType() == OfficialAccPayBaseAction.TC_WEIXIN 
                		|| send.getCollectionType() == OfficialAccPayBaseAction.TC_SHANGLIANCHU
                        || send.getCollectionType() == OfficialAccPayBaseAction.TC_JQ_SECOND
                        || send.getCollectionType() == OfficialAccPayBaseAction.TC_HSM
                        || send.getCollectionType() == OfficialAccPayBaseAction.TC_JQ_QR
                    ){
                    result = new JSONObject();
                    result.put("payUrl", rs.getPayUrl());
                    result.put("reqCode", rs.getReqCode());
                    result.put("msg", rs.getReqMsg());
                    result.put("appId", rs.getAppId());
                    result.put("timestamp", rs.getTimestamp());
                    result.put("nonceStr", rs.getNonceStr());
                    result.put("prepayId", rs.getPrepayId());
                    result.put("paySign", rs.getPaySign());
                    result.put("orderId", rs.getResultCode());
                    result.put("externalId", scanCodePayParam.getOutTradeNo());
                    result.put("channel", send.getCollectionType());
                    result.put("payInfo",rs.getPayInfo());
                    result.put("code", rs.getStatus());

                    if(!rs.getReqCode().equals("0000")){
                        //获取支付路径失败则直接标记交易失败
                        result = purchaseResolveResult(send, rs, transOrder, transPriorSettle, user, tc);
                    }else {
                        transPriorSettle.setResponseCode("0002");
                        transPriorSettle.setMerchantId(rs.getCustomerNo());
                        transPriorSettle.setBankMessage("订单创建成功,等待用户付款!");
                        transPriorSettleService.updateEntity(transPriorSettle);

//                        if(!ConConfig.isFormal()){
//                            CloseableHttpClient client = null;
//                            String notifyUrl = "http://localhost:8000/proOneMobile/JQNotify.action?code=0&message=交易成功&externalId="+scanCodePayParam.getOutTradeNo();
//
//                            try {
//                                HttpGet httpGet = new HttpGet(notifyUrl);
//                                client = HttpClients.createDefault();
//                                client.execute(httpGet);
//
//                            }catch (Exception e){
//                                e.printStackTrace();
//                                log.error("【进钱-秒到收款】 系统异常!");
//                                throw e;
//                            }
//                        }
                    }
                }else {
                    //解析结果
                    result = purchaseResolveResult(send, rs, transOrder, transPriorSettle, user, tc);
                    log.info(result.toString());
                }
                sendWeChatMsg(result.toString());
            } else {
                log.info("我要收款时, 用户Id=" + userId + " 对应的用户不存在!");
                sendAppErrorMsg("6012", userId + "");
            }
        } catch (Exception e) {
            e.printStackTrace();
            //TODO:异常处理  超时处理
            revocationOrderTimeOut(send, transPriorSettle,scanCodePayParam);
            throw e;
        } finally {
            send = null;
            transPriorSettle = null;
            transOrder = null;
            result = null;
        }
        return null;
    }

    /**
     * 计算手续费
     *
     * @param transMoney
     * @param feeRate
     * @return
     */
    private Double calculateFee(Double transMoney, Double feeRate) {
        double fee = NumberUtil.roundF2(feeRate * transMoney);
        return fee;
    }

    /**
     * 进钱秒到回调接口
     * @return
     */
    public String JQNotify(){
        log.debug("XXXXXXXXXXXXXXXXXXXXXXXXX  进钱秒到结果通知接口  XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
        try {
            if(ConConfig.isFormal()){
                String param = (String)getRequest().getParameterNames().nextElement();
                log.info("【进钱-回调 请求参数】:" + param);
                if(StringUtils.isNotBlank(param)) {
                    JSONObject js = JSONObject.fromObject(param);
                    String code = js.getString("code");//响应码
                    String message = js.getString("message");//响应码对应信息
                    String externalId = js.getString("externalId");//收款订单号

                    TransOrder transOrder = transOrderService.searchOrderByOrderNum(externalId);

                    if(1 == transOrder.getStatus()){
                        log.info("【进钱-回调】: 订单号 " + externalId + "交易成功,已收到回调!");
                        //交易成功响应一个0即可
                        getResponse().getOutputStream().write("0".getBytes());
                        getResponse().flushBuffer();
                        return null;
                    }

                    TransPriorSettle transPriorSettle = new TransPriorSettle();
                    transPriorSettle.setOrderNum(externalId);
                    transPriorSettle = transPriorSettleService.searchEntity(transPriorSettle);

                    Long sendId = transPriorSettle.getSendId();
                    Qian4SendLog send = new Qian4SendLog();
                    send.setId(sendId);
                    send = qian4SendLogService.searchEntity(send);

                    User user = userService.getUserById(transOrder.getUserId());

                    Tchannel tc = new Tchannel();
                    tc.setCode(transPriorSettle.getCollectionType());
                    tc = tchannelService.searchEntity(tc);

                    PurchaseResult rs = new PurchaseResult();
                    if (code.equals("0")) {
                        rs.setReqCode("0000");
                        rs.setReqMsg("交易成功!");
                        rs.setStatus(1);

                        //交易成功响应一个0即可
                        getResponse().getOutputStream().write("0".getBytes());
                        getResponse().flushBuffer();

                    } else {
                        rs.setReqCode(code);
                        rs.setReqMsg(message);
                        rs.setStatus(0);
                    }

                    purchaseResolveResult(send, rs, transOrder, transPriorSettle, user, tc);

                    if (code.equals("0") && OfficialAccPayBaseAction.TC_JQ_SECOND == tc.getCode().intValue() && user.getRoleType() != 3) {//交易成功,并且是秒到接口,并且不是接口用户
                        Double chargeAmount = transOrder.getChargeAmount();
                        double cashMoneyFee = 0.00;//提现手续费,收款代扣,无需计算提现手续费
                        double cashMoney = chargeAmount - cashMoneyFee;
                        JQSecondCashMoney(user, externalId, cashMoney, cashMoneyFee);
                    }
                    if(code.equals("0") && StringUtils.isNotBlank(transOrder.getOtherData())){//去发起回调 otherData回调地址
                        JSONObject res = remoteNotify(transOrder,send,user);

                        Date date = new Date();
                        RemoteNotify remoteNotify = new RemoteNotify();
                        remoteNotify.setId(genOrderNo(user.getChannelId()));
                        remoteNotify.setCounts(1);
                        remoteNotify.setOrderNum(transOrder.getOrderNum());
                        remoteNotify.setMerchantOrderNum(send.getMerchantOrderId());
                        remoteNotify.setRequestUrl(transOrder.getOtherData());
                        remoteNotify.setCreateDate(date);
                        remoteNotify.setLastDate(date);
                        remoteNotify.setRequestData(res.getString("requestData"));
                        remoteNotify.setStatus(0);

                        if(res.getString("code").contains("0000")){//对方成功收到回调
                            remoteNotify.setStatus(1);
                        }
                        remoteNotifyService.insertEntity(remoteNotify);
                    }
                }
            } else{

                String code = getRequest().getParameter("code");//响应码
                String message = getRequest().getParameter("message");//响应码对应信息
                String externalId = getRequest().getParameter("externalId");//订单号

                TransOrder transOrder = transOrderService.searchOrderByOrderNum(externalId);

                if(1 == transOrder.getStatus()){
                    //交易成功响应一个0即可
                    getResponse().getOutputStream().write("0".getBytes());
                    getResponse().flushBuffer();
                    log.info("【进钱-回调】: 订单号 " + externalId + "交易成功,已收到回调!");
                    return null;
                }

                TransPriorSettle transPriorSettle = new TransPriorSettle();
                transPriorSettle.setOrderNum(externalId);
                transPriorSettle = transPriorSettleService.searchEntity(transPriorSettle);

                Long sendId = transPriorSettle.getSendId();
                Qian4SendLog send = new Qian4SendLog();
                send.setId(sendId);
                send = qian4SendLogService.searchEntity(send);

                User user = userService.getUserById(transOrder.getUserId());

                Tchannel tc = new Tchannel();
                tc.setCode(transPriorSettle.getCollectionType());
                tc = tchannelService.searchEntity(tc);

                PurchaseResult rs = new PurchaseResult();
                if (code.equals("0")) {
                    rs.setReqCode("0000");
                    rs.setReqMsg("交易成功!");
                    rs.setStatus(1);

                    //交易成功响应一个0即可
                    getResponse().getOutputStream().write("0".getBytes());
                    getResponse().flushBuffer();

                } else {
                    rs.setReqCode(code);
                    rs.setReqMsg(message);
                    rs.setStatus(0);
                }

                purchaseResolveResult(send, rs, transOrder, transPriorSettle, user, tc);

                if (code.equals("0") && OfficialAccPayBaseAction.TC_JQ_SECOND == tc.getCode().intValue()) {//交易成功,并且是秒到接口
                    Double chargeAmount = transOrder.getChargeAmount();
                    double cashMoneyFee = 0.00;//提现手续费,收款代扣,无需计算提现手续费
                    double cashMoney = chargeAmount - cashMoneyFee;
                    JQSecondCashMoney(user, externalId, cashMoney, cashMoneyFee);
                }
                if(code.equals("0") && StringUtils.isNotBlank(transOrder.getOtherData())){//去发起回调 otherData回调地址
                    JSONObject res = remoteNotify(transOrder,send,user);

                    Date date = new Date();
                    RemoteNotify remoteNotify = new RemoteNotify();
                    remoteNotify.setId(genOrderNo(user.getChannelId()));
                    remoteNotify.setCounts(1);
                    remoteNotify.setOrderNum(transOrder.getOrderNum());
                    remoteNotify.setMerchantOrderNum(send.getMerchantOrderId());
                    remoteNotify.setRequestUrl(transOrder.getOtherData());
                    remoteNotify.setCreateDate(date);
                    remoteNotify.setLastDate(date);
                    remoteNotify.setRequestData(res.getString("requestData"));
                    remoteNotify.setStatus(0);

                    if(res.getString("code").contains("0000")){//对方成功收到回调
                        remoteNotify.setStatus(1);
                    }
                    remoteNotifyService.insertEntity(remoteNotify);
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }

    private String JQSecondCashMoney(User user, String OrgOrderNum, Double cashMoney,Double cashMoneyFee ) {
        userId = user.getUserId();
        functionKey = "CASHMONEY";
        log.debug("functionKey = " + functionKey);
        log.debug("userId = " + userId);
        log.debug("cashMoney = " + cashMoney);
        log.debug("cashMoneyFee = " + cashMoneyFee);
        log.debug("OrgOrderNum = " + OrgOrderNum);

        // 查询原始收款订单
        TransOrder orgOrder = new TransOrder();
        try {
            Date date = new Date();

            // 查询原始收款订单
            orgOrder.setOrderNum(OrgOrderNum);
            orgOrder = transOrderService.searchEntity(orgOrder);

            if (null == orgOrder) {
                log.info("安全提现时, 不存在该订单！");
                sendWeChatErrorMsg("6086");
                return null;
            }
            if (1 != orgOrder.getOrderTypeId().intValue()) {// 订单不是收款订单
                log.info("安全提现时, 订单不是收款订单！");
                sendWeChatErrorMsg("6087");
                return null;
            }
            if (1 != orgOrder.getStatus().intValue()) {// 收款订单不是交易成功的订单
                log.info("提现失败，收款订单不是交易成功的订单！");
                sendWeChatErrorMsg("6092");
                return null;
            }

            double chargeAmount = orgOrder.getChargeAmount();
            if (chargeAmount != NumberUtil.roundF2((cashMoneyFee + cashMoney)) && chargeAmount != cashMoney) {//金额不相等
                log.info("安全提现时, 传入提现金额与手续费不符！");
                return null;
            }

            if (null != orgOrder.getCashOrderNum()) {
                TransOrder cashOrder = new TransOrder();
                cashOrder.setOrderNum(orgOrder.getCashOrderNum());
                cashOrder = transOrderService.searchEntity(cashOrder);
                if (null == cashOrder || cashOrder.getStatus().intValue() != 0) {
                    return null;
                }
            }

            // 金额是否足够
            boolean isZhugou = userMoneyService.moneyTheAdequacy(user.getId(), chargeAmount, 1);
            if (!isZhugou) {
                log.info("提现错误，金额不足！");
                sendWeChatErrorMsg("6082", chargeAmount + "");
                return null;
            }

            TransOrder transOrder = new TransOrder();
            transOrder.setOrderNum(genOrderNo(user.getChannelId()));
            transOrder.setOrderTypeId(OrderTypeUtil.JQ_CASH_MONEY);// 自动提现
            transOrder.setUserId(user.getId());
            transOrder.setTransMoney(chargeAmount);

            transOrder.setFeeMoney(cashMoneyFee);// fee);//手续费
            transOrder.setBrokerage(0.0000);// brokerage);
            transOrder.setDealerBrokerage(0.0000);
            transOrder.setChargeAmount(cashMoney);
            transOrder.setRootCategory("账务管理");
            transOrder.setCategory("提现");
            transOrder.setObjectiveName(user.getCardholder());// 对方姓名
            transOrder.setObjectiveCard(user.getBankCard());// 对方银行卡
            transOrder.setObjectiveOpBank(user.getOpeningBank());// 对方银行

            transOrder.setStatus(2);
            transOrder.setClearing(0);// 结算状态 0未结算 1结算
            transOrder.setDescription("系统结算");// 交易详情
            transOrder.setCreateDate(date);
            transOrder.setUpdateLongTime(date.getTime());

            transOrder.setObjectiveBBank(user.getBranchesBank());// 对方。银行支行
            transOrder.setObjectiveBBProvince(user.getBBankProvince());
            transOrder.setObjectiveBBCity(user.getBBankCity());
            transOrder.setObjectiveMobile(user.getMobile());// 对方手机号
            transOrder.setObjectiveBBankCode(user.getBranchesBankCode());
            transOrder.setObjectiveAccBankCode(user.getAccBankCode());
            transOrder.setTerminalTypeId(user.getTerminalTypeId());
            transOrder.setRoleId(2l);
            transOrder.setOrgOrderNum(orgOrder.getOrderNum());// 原订单编号
            transOrder.setFeeRate(user.getCashRate());// 订单费率
            transOrder.setFdMaxFee(0.00);// 用户封顶最高
            transOrder.setFdMinFee(2.00);// 用户封顶最低
            transOrder.setClientType(orgOrder.getClientType());

            // 修改原订单
            transOrderService.updateCashOrderByNum(orgOrder.getOrderNum(), transOrder.getOrderNum());
            //生成提现订单
            cashMoneyService.secondCashMoneySafe(transOrder);

            log.info("生成提现订单成功, 订单号: " + transOrder.getOrderNum() + " ,原始收款订单号: " + orgOrder.getOrderNum());

        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 通知第三方接口交易结果
     * @return
     */
    public JSONObject remoteNotify(TransOrder transOrder,Qian4SendLog send,User user){
        String reqUrl = transOrder.getOtherData();
        SortedMap<String,String> map = new TreeMap<>();
        map.put("version", "1.0.0");
        map.put("code","0");//成功
        map.put("message", "交易成功");
        map.put("externalId", send.getMerchantOrderId());
        map.put("transAmount", String.valueOf(NumberUtil.roundF2(transOrder.getTransMoney()*100).longValue()));//金额转为分
        map.put("selfData", DesUtil.generate32Key());
        map.put("customerNo", String.valueOf(user.getId()));

        Map<String,String> params = SignUtils.paraFilter(map);
        StringBuilder buf = new StringBuilder((params.size() +1) * 10);
        SignUtils.buildPayParams(buf,params,false);
        String preStr = buf.toString();
        String sign = MD5.sign(preStr, "&key=" + user.getPassword(), "utf-8");
        map.put("sign", sign);

        Map<String,Object> paramMap = new HashMap<>();
        paramMap.putAll(map);

        JSONObject jsonObject = JSONObject.fromObject(paramMap);

        CloseableHttpResponse response = null;
        CloseableHttpClient client = null;
        JSONObject result = new JSONObject();
        result.put("requestData",jsonObject.toString());
        log.info("回调请求参数: " + jsonObject.toString());
        try {
            HttpPost httpPost = new HttpPost(reqUrl);
            StringEntity entityParams = new StringEntity(jsonObject.toString(), "UTF-8");
            entityParams.setContentType("application/json");
            httpPost.setEntity(entityParams);
            RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(10000).setConnectionRequestTimeout(10000).setSocketTimeout(10000).build();
            httpPost.setConfig(requestConfig);
            client = HttpClients.createDefault();
            response = client.execute(httpPost);
            if (response != null && response.getEntity() != null) {
                String code = EntityUtils.toString(response.getEntity(),"UTF-8");
                log.info("回调响应参数: " + code);
                result.put("code",code);
            }
        }catch (Exception e){
            log.error("向下游机构发起回调失败: "+e.getMessage());
            result.put("code","0001");
        }

        return result;
    }

    /**
     *同步收款订单状态
     */
    public void getJQOrderStatus(){
        try {
            String startTime = getRequest().getParameter("startDate");
            String endTime = getRequest().getParameter("endDate");
            Date startDate = new Date();
            Date endDate = new Date();

            Date date = new Date();

            if(StringUtils.isBlank(startTime)){
                Calendar calendar = Calendar.getInstance();
                calendar.add(Calendar.DAY_OF_YEAR, -3);
                startDate = calendar.getTime();
            }else {
                startDate.setTime(Long.valueOf(startTime));
            }

            if(StringUtils.isNotBlank(endTime)){
                endDate.setTime(Long.valueOf(endTime));
            }

            TransOrder transOrder = new TransOrder();
            transOrder.setStartDate(startDate);
            transOrder.setEndDate(endDate);
            transOrder.setStatus(3);//未付款
            transOrder.setOrderTypeId(1l);//收款订单
            List<TransOrder> transOrderList = transOrderService.searchEntityList(transOrder);
            if(transOrderList.size() > 0){
                for(TransOrder order : transOrderList){
                    String orderNum = order.getOrderNum();

                    TransPriorSettle transPriorSettle = new TransPriorSettle();
                    transPriorSettle.setOrderNum(orderNum);
                    transPriorSettle = transPriorSettleService.searchEntity(transPriorSettle);

                    Qian4SendLog send = new Qian4SendLog();
                    send.setId(transPriorSettle.getSendId());
                    send = qian4SendLogService.searchEntity(send);

                    User user = userService.getUserById(order.getUserId());

                    Tchannel tc = new Tchannel();
                    tc.setCode(transPriorSettle.getCollectionType());
                    tc = tchannelService.searchEntity(tc);

                    String merchantId = transPriorSettle.getMerchantId();
                    if(StringUtils.isBlank(merchantId)){
                        int collectionType = transPriorSettle.getCollectionType();
                        if(collectionType == OfficialAccPayBaseAction.TC_JQ_SECOND){
                            merchantId = user.getJQCusId();
                        }else if(collectionType == OfficialAccPayBaseAction.TC_JQ){
                            merchantId = "8611116424";
                        }else if(collectionType == OfficialAccPayBaseAction.TC_JQ_QR){
                            if(3 == user.getRoleType().intValue()){
                                merchantId = ConConfig.getAttribute("ZYX_JQQR_CUSID");
                            }else {
                                merchantId = ConConfig.getAttribute("HSM_JQQR_CUSID");
                            }
                        }else if(collectionType == OfficialAccPayBaseAction.TC_JQ_SDK){
                            merchantId = ConConfig.getAttribute("JQ_SDK_PAY_CUSID");
                        }
                    }

                    SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
                    String reqDate = sdf.format(date);

                    SortedMap<String,String> map = new TreeMap<>();
                    map.put("version", "1.0.0");
                    map.put("reqDate", reqDate);
                    map.put("customerNo", merchantId);
                    map.put("externalId", orderNum);
                    map.put("requestIp","118.145.2.70");

                    Map<String,String> params = SignUtils.paraFilter(map);
                    StringBuilder buf = new StringBuilder((params.size() +1) * 10);
                    SignUtils.buildPayParams(buf,params,false);
                    String preStr = buf.toString();
                    String sign = MD5.sign(preStr, "&key=4683462567867C6120A251F8A1B0D6A1", "utf-8");
                    map.put("sign", sign);

                    JSONObject jsonObject = JSONObject.fromObject(map);
                    log.info("【进钱-交易查询 请求参数】:" + jsonObject.toString());

                    String reqUrl = "https://boss.1spay.com/posboss/findTransStatusReq.action";

                    CloseableHttpResponse response = null;
                    CloseableHttpClient client = new SSLClient();
                    try {
                        HttpPost httpPost = new HttpPost(reqUrl);
                        StringEntity entityParams = new StringEntity(jsonObject.toString(), "utf-8");
                        httpPost.setEntity(entityParams);
                        response = client.execute(httpPost);
                        if (response != null && response.getEntity() != null) {
                            String result = EntityUtils.toString(response.getEntity());
                            log.info("【进钱-交易查询 响应参数】:" + result);
                            JSONObject resultJson = JSONObject.fromObject(result);
                            if(resultJson.containsKey("code") && resultJson.getString("code").equals("0000")){
                                if(resultJson.containsKey("transStatus") && resultJson.getString("transStatus").equals("0000")){//transStatus
                                    if(resultJson.containsKey("externalId") && !resultJson.getString("externalId").equals(orderNum)){
                                        log.info("【进钱-交易查询】查询订单号: " + orderNum + " 与响应订单号: " + resultJson.getString("externalId") + " 不匹配");
                                        continue;
                                    }
                                    log.info("【进钱-交易查询】收款订单号: " + orderNum + " 查询结果: 交易成功");
                                    PurchaseResult rs = new PurchaseResult();
                                    rs.setReqCode("0000");
                                    rs.setReqMsg("交易成功!");
                                    rs.setStatus(1);
                                    //去更新收款结果
                                    purchaseResolveResult(send, rs, order, transPriorSettle, user, tc);

                                    if (OfficialAccPayBaseAction.TC_JQ_SECOND == tc.getCode().intValue() && user.getRoleType() != 3) {//交易成功,并且是秒到接口,并且不是接口用户
                                        Double chargeAmount = order.getChargeAmount();
                                        double cashMoneyFee = 0.00;//提现手续费,收款代扣,无需计算提现手续费
                                        double cashMoney = chargeAmount - cashMoneyFee;
                                        JQSecondCashMoney(user, orderNum, cashMoney, cashMoneyFee);
                                    }
                                    if(StringUtils.isNotBlank(order.getOtherData())){//去发起回调 otherData回调地址
                                        JSONObject res = remoteNotify(order,send,user);
                                        RemoteNotify remoteNotify = new RemoteNotify();
                                        remoteNotify.setId(genOrderNo(user.getChannelId()));
                                        remoteNotify.setCounts(1);
                                        remoteNotify.setOrderNum(orderNum);
                                        remoteNotify.setMerchantOrderNum(send.getMerchantOrderId());
                                        remoteNotify.setRequestUrl(order.getOtherData());
                                        remoteNotify.setCreateDate(date);
                                        remoteNotify.setLastDate(date);
                                        remoteNotify.setRequestData(res.getString("requestData"));
                                        remoteNotify.setStatus(0);

                                        if(res.getString("code").contains("0000")){//对方成功收到回调
                                            remoteNotify.setStatus(1);
                                        }
                                        remoteNotifyService.insertEntity(remoteNotify);
                                    }
                                }else {
                                    String transStatus = resultJson.getString("transStatus");
                                    String transMessage = "";
                                    if(transStatus.equals("0001")){
                                        transMessage = "未付款";
                                    }else if(transStatus.equals("0002")){
                                        transMessage = "交易已撤销";
                                    }else if(transStatus.equals("0003")){
                                        transMessage = "未找到对应交易";
                                    }else {
                                        transMessage = "查询未响应";
                                    }
                                    log.info("【进钱-交易查询】收款订单号: " + orderNum + " 查询结果: " + transMessage);
                                    continue;
                                }
                            }else {
                                log.info("【进钱-交易查询】收款订单号: " + orderNum + " 响应异常!");
                                continue;
                            }
                        }
                    }catch (Exception e){
                        log.info("【进钱-交易查询】收款订单号: " + orderNum + " 查询异常: " + e.getMessage());
                        continue;
                    }
                }
            }
        } catch (Exception e) {
            log.error("【进钱-交易查询】系统异常: " + e.getMessage());
            e.printStackTrace();
        }
    }

}
